﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Runtime.Serialization.Json;
using SedCup.Code.Model;
using Newtonsoft.Json;


namespace SEDCupConsole
{
    public class Example
    {
        private static List<AgentTaskPair> agentTaskPairs = new List<AgentTaskPair>();
        private static Dictionary<string, List<Task>> strategy;
        

        class AgentTaskPair
        {
            public AgentTaskPair(Agent agent, Task task)
            {
                TaskToDo = task;
                AgentToGo = agent;
                doingJob = -1;
            }
            public Task TaskToDo { get; set; }
            public Agent AgentToGo { get; set; }
            public int doingJob { get; set; }
        }

        public static void ConnectToServer(string jsonData, string TeamString)
        {
                string url = TeamString;
                HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
                setAuthInfo(request);
                request.Method = "POST";
                request.ContentType = "application/json";
                request.Timeout = 1000000;
                if (!string.IsNullOrEmpty(jsonData))
                {
                    Stream requestStream = request.GetRequestStream();
                    byte[] restData = Encoding.UTF8.GetBytes(jsonData);
                    requestStream.Write(restData, 0, restData.Length);
                    requestStream.Close();
                }
                while (true)
                {
                try
                {
                    HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                    
                    using (StreamReader reader = new StreamReader(response.GetResponseStream()))
                    {
                        ClientRequest clientRequest = new ClientRequest();
                        string res = reader.ReadToEnd();
                        ServerResponse serverResponse = JsonConvert.DeserializeObject<ServerResponse>(res);
                        int tempTurn = serverResponse.turn;
                        serverResponse.turn = (serverResponse.turn % 2 == 0) ? serverResponse.turn / 2 : ((serverResponse.turn / 2) + 1);
                        if (serverResponse.turn == 1)
                        {
                            strategy = SearchForJob.DetermineWinnerStrategy(serverResponse);
                            int junior = strategy["junior"].Count;
                            int senior = strategy["senior"].Count;
                            int guru = strategy["guru"].Count;

                            clientRequest.turn = serverResponse.turn;
                            clientRequest.move = new List<AgentToMove>();
                            clientRequest.fire = new List<string>();
                            clientRequest.dojob = new List<string>();
                            clientRequest.hire = new List<int>();
                            clientRequest.hire.Add(junior);
                            clientRequest.hire.Add(senior);
                            clientRequest.hire.Add(guru);
                        }

                        if (serverResponse.turn == 2)
                        {
                            List<Agent> agents = serverResponse.agents;

                            foreach (Agent agent in agents)
                            {
                                if (agent.type.Equals("junior"))
                                {
                                    agentTaskPairs.Add(new AgentTaskPair(agent, strategy["junior"][0]));
                                    strategy["junior"].RemoveAt(0);
                                }

                                if (agent.type.Equals("senior"))
                                {
                                    agentTaskPairs.Add(new AgentTaskPair(agent, strategy["senior"][0]));
                                    strategy["senior"].RemoveAt(0);
                                }

                                if (agent.type.Equals("guru"))
                                {
                                    agentTaskPairs.Add(new AgentTaskPair(agent, strategy["guru"][0]));
                                    strategy["guru"].RemoveAt(0);
                                }
                            }
                        }

                        if (agentTaskPairs.Count != 0 && serverResponse.turn >= 2)
                        {
                            clientRequest.turn = serverResponse.turn;
                            clientRequest.hire = new List<int>() { 0, 0, 0 };
                            clientRequest.move = new List<AgentToMove>();
                            clientRequest.dojob = new List<string>();
                            clientRequest.fire = new List<string>();

                            List<AgentTaskPair> toRemove = new List<AgentTaskPair>();

                            foreach (AgentTaskPair taskPair in agentTaskPairs)
                            {
                                if (taskPair.AgentToGo.coordinate != taskPair.TaskToDo.coordinate)
                                {
                                    int direction = Neighbour.getShortestRoadStep(taskPair.AgentToGo.coordinate, serverResponse.mapSize, serverResponse.roadBlocks, taskPair.TaskToDo.coordinate);
                                    AgentToMove move = new AgentToMove(taskPair.AgentToGo.agentId, direction);
                                    clientRequest.move.Add(move);
                                }
                                else if (taskPair.doingJob == -1)
                                {
                                    clientRequest.dojob.Add(taskPair.AgentToGo.agentId);
                                    taskPair.doingJob = serverResponse.turn + 2;
                                }
                                else if (taskPair.doingJob + taskPair.TaskToDo.duration > serverResponse.turn)
                                {
                                    clientRequest.fire.Add(taskPair.AgentToGo.agentId);
                                    toRemove.Add(taskPair);
                                }
                            }

                            foreach (AgentTaskPair taskPair in toRemove)
                            {
                                agentTaskPairs.Remove(taskPair);
                            }

                        }
                        else if (serverResponse.turn != 1)
                        {
                            clientRequest.turn = serverResponse.turn;
                            clientRequest.hire = new List<int>() { 0, 0, 0 };
                            clientRequest.move = new List<AgentToMove>();
                            clientRequest.dojob = new List<string>();
                            clientRequest.fire = new List<string>();
                        }

                        clientRequest.turn = tempTurn;
                        DataContractJsonSerializer serout = new DataContractJsonSerializer(typeof(ClientRequest));
                        MemoryStream ms2 = new MemoryStream();
                        serout.WriteObject(ms2, clientRequest);
                        string json = Encoding.Default.GetString(ms2.ToArray());
                        ms2.Close();

                        request = (HttpWebRequest)HttpWebRequest.Create(url);
                        request.Timeout = 1000000;
                        setAuthInfo(request);
                        request.Method = "POST";
                        request.ContentType = "application/json";

                        Stream requestStream = request.GetRequestStream();
                        byte[] restData = Encoding.UTF8.GetBytes(json);
                        requestStream.Write(restData, 0, restData.Length);
                        requestStream.Close();

                        
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Excepion occured while connecting to the server" + ex.Message + "\n" + ex.StackTrace);
                }
            }
        }

        public static void ConnectToServer2(object param)
        {
            string jsonData = "{\"turn\":0,\"hire\":[0,0,0],\"move\":[],\"dojob\":[],\"fire\":[]}";
            string url = @"http://localhost:3723/sedcup2013/teams/Client2";
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
            setAuthInfo(request);
            request.Method = "POST";
            request.ContentType = "application/json";
            if (!string.IsNullOrEmpty(jsonData))
            {
                Stream requestStream = request.GetRequestStream();
                byte[] restData = Encoding.UTF8.GetBytes(jsonData);
                requestStream.Write(restData, 0, restData.Length);
                requestStream.Close();
            }
            try
            {
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                using (StreamReader reader = new StreamReader(response.GetResponseStream()))
                {
                    string res = reader.ReadToEnd();
                    
                    MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(res));

                    DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(ServerResponse));
                    ServerResponse serverResponse = ser.ReadObject(ms) as ServerResponse;
                    ms.Close();

                    Console.WriteLine("Received content: " + res);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Excepion occured while connecting to the server" + ex.Message + "\n" + ex.StackTrace);
            }
        }

        public static void setAuthInfo(HttpWebRequest request)
        {
            string authInfo = "login" + ":" + "secret";
            authInfo = Convert.ToBase64String(Encoding.UTF8.GetBytes(authInfo));
            request.Headers["Authorization"] = "Basic " + authInfo;
        }
    }
}
